package cn.zhz.customview.view.tiktok;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;

import androidx.annotation.Nullable;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import androidx.interpolator.view.animation.LinearOutSlowInInterpolator;
import cn.zhz.customview.R;

/**
 * @author: zhuanghz
 * @createdTime: 2019/6/6 15:34
 * @desc: 模仿抖音上点赞按钮的动画效果
 * 1、点击后切换到彩色图片
 * 2、缩小至不见
 * 3、外圆出来呈现最大的
 * 4、内园出来，并放大，同时彩色爱心图片放大
 * 5、周边出来小圆点，由小到大在变小消失
 */
public class TikTokStarView extends View {

    private int size;
    private int bitmapMaxSize;
    private float circleRadius;
    private Paint paint;
    private Paint innerPaint = new Paint();
    private Paint bigCirclePaint=new Paint();
    private Bitmap nBitmap;//默认图片
    private Bitmap sBitmap;//选中效果
    private final int bitmapMargin = 60;
    private boolean isLove;//true表示当前显示的是喜欢的图片，false表示显示的是不喜欢的图片

    private AnimatorSet animControl = new AnimatorSet();

    private ValueAnimator love2SmallAnim;
    private ValueAnimator love2BigAnim;
    private ValueAnimator bigCircleAnim;
    private ValueAnimator smallCircleAnim;
    private ValueAnimator dotAnim;
    private ValueAnimator dotTranslationAnim;
    private float innerCircleValue;
    private float outCircleValue;

    //外环小圆个数
    private final int DOTS_COUNT = 6;
    //外环小圆位置角度
    private final int DOTS_POSITION_ANGLE = 360 / DOTS_COUNT;
    private final int DOTS_MAX_RADIUS = 12;
    private float dotsRadius;
    private float dotsOffset;


    public TikTokStarView(Context context) {
        this(context, null);
    }

    public TikTokStarView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TikTokStarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setFilterBitmap(true);
        paint.setAntiAlias(true);
        paint.setColor(Color.parseColor("#FD7878"));
        paint.setStyle(Paint.Style.FILL);

        bigCirclePaint.setFilterBitmap(true);
        bigCirclePaint.setAntiAlias(true);
        bigCirclePaint.setColor(Color.parseColor("#FD7878"));
        bigCirclePaint.setStyle(Paint.Style.FILL);

        innerPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
        nBitmap = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.ic_love_normal);
        sBitmap = BitmapFactory.decodeResource(getContext().getResources(), R.mipmap.ic_love_select);
        createBitmapAnim();
        createCircleAnimSet();
        createDotAnimSet();

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //定义大小，根据上面获取到的图片计算一次大小
        //由于是两张图片，因此都要计算一下，以便控制画布的大小
        bitmapMaxSize = Math.max(Math.max(nBitmap.getWidth(), nBitmap.getHeight()),
                Math.max(sBitmap.getWidth(), sBitmap.getHeight()));
        //考虑到圆圈的动画比图片大，因此画布的尺寸也会比图片大
        size = bitmapMaxSize + bitmapMargin * 2;
        setMeasuredDimension(measureWidth(size, widthMeasureSpec), measureHeight(size, heightMeasureSpec));
        circleRadius = (bitmapMaxSize / 2 + 30);
    }


    /**
     * 计算宽度
     */
    private int measureWidth(int size, int widthMeasureSpec) {
        int result = size;
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);
        switch (specMode) {
            case MeasureSpec.EXACTLY:
                if (specSize > size) {
                    result = specSize;
                }
                break;
        }
        return result;
    }


    /**
     * 计算高度，和宽度计算一致
     */
    private int measureHeight(int size, int heightMeasureSpec) {
        int result = size;
        int specMode = MeasureSpec.getMode(heightMeasureSpec);
        int specSize = MeasureSpec.getSize(heightMeasureSpec);
        switch (specMode) {
            case MeasureSpec.EXACTLY:
                if (specSize > size) {
                    result = specSize;
                }
                break;
        }
        return result;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制爱心图片
        drawLoveBitmap(canvas);
        //绘制外圆和内圆
        drawCircle(canvas);
        //绘制周边小圆点
        drawOuterDotsFrame(canvas);

    }

    float value = 1f;

    /**
     * 绘制爱心图片
     */
    private void drawLoveBitmap(Canvas canvas) {
        if (!isLove) {
            canvas.save();
            canvas.drawBitmap(nBitmap, (getWidth() - nBitmap.getWidth()) / 2, (getHeight() - nBitmap.getHeight()) /
                    2, paint);
            canvas.restore();
        } else {
            canvas.save();
            canvas.scale(value, value, getWidth() / 2, getHeight() / 2);
            canvas.drawBitmap(sBitmap, (getWidth() - sBitmap.getWidth()) / 2, (getHeight() - sBitmap.getHeight()) /
                    2, paint);
            canvas.restore();
        }
    }

    private void drawCircle(Canvas canvas) {
        canvas.save();
        int sc = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG);//创建一个新的layer
        if (smallCircleAnim.isRunning() || bigCircleAnim.isRunning()) {
            canvas.drawCircle(getWidth() / 2, getHeight() / 2, outCircleValue * circleRadius, bigCirclePaint);
            canvas.drawCircle(getWidth() / 2, getHeight() / 2, innerCircleValue * circleRadius, innerPaint);
        }
        canvas.restoreToCount(sc);
        canvas.restore();
    }


    private void drawOuterDotsFrame(Canvas canvas) {
        for (int i = 0; i < DOTS_COUNT; i++) {
            int cX = (int) (getWidth() / 2 + (circleRadius - 5 + dotsOffset) * Math.cos(i * DOTS_POSITION_ANGLE * Math.PI / 180));
            int cY = (int) (getHeight() / 2 + (circleRadius - 5 + dotsOffset) * Math.sin(i * DOTS_POSITION_ANGLE * Math.PI / 180));
            canvas.drawCircle(cX, cY, dotsRadius, paint);
        }
    }

    private AnimatorSet bitmapAnimSet=new AnimatorSet();
    private void createBitmapAnim() {
        love2SmallAnim = ValueAnimator.ofFloat(1.0f, 0f);
        love2SmallAnim.setDuration(300);
        love2BigAnim = ValueAnimator.ofFloat(0.3f, 1.0f);
        love2BigAnim.setDuration(500);
        love2BigAnim.setInterpolator(new OvershootInterpolator(1.1f));

        love2SmallAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                value = (float) love2SmallAnim.getAnimatedValue();
                postInvalidate();
            }
        });

        love2BigAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                value = (float) love2BigAnim.getAnimatedValue();
                postInvalidate();
            }
        });
        bitmapAnimSet.play(love2BigAnim).after(love2SmallAnim);
    }

    private AnimatorSet circleAnimSet=new AnimatorSet();
    private void createCircleAnimSet() {
        smallCircleAnim = ValueAnimator.ofFloat(0f, 1f);
        smallCircleAnim.setDuration(120);
        smallCircleAnim.setInterpolator(new DecelerateInterpolator());

        bigCircleAnim = ValueAnimator.ofFloat(0.5f, 1f);
        bigCircleAnim.setDuration(250);
        bigCircleAnim.setInterpolator(new DecelerateInterpolator());
        bigCircleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                outCircleValue = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        smallCircleAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                innerCircleValue = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        smallCircleAnim.setStartDelay(120);
        circleAnimSet.play(bigCircleAnim).with(smallCircleAnim);

    }

    private AnimatorSet dotAnimSet=new AnimatorSet();
    private void createDotAnimSet() {
        dotAnim = ValueAnimator.ofFloat(0, 1.0f,0f);
        dotAnim.setDuration(400);

        dotTranslationAnim = ValueAnimator.ofFloat(0, 1.0f);
        dotTranslationAnim.setDuration(400);

        dotAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                dotsRadius = (float) animation.getAnimatedValue() * DOTS_MAX_RADIUS;

            }
        });

        dotTranslationAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                dotsOffset = (float) animation.getAnimatedValue() * 30;
                postInvalidate();
            }
        });
        dotAnimSet.play(dotAnim).with(dotTranslationAnim);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                checkClickPoint(event);
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return super.onTouchEvent(event);
    }


    /**
     * 判断是否点击在爱心位置上
     */
    private void checkClickPoint(MotionEvent event) {
        float cx = event.getX();
        float cy = event.getY();

        float lX = (getWidth() - sBitmap.getWidth()) / 2;
        float rX = (getWidth() + sBitmap.getWidth()) / 2;
        float ty = (getHeight() - sBitmap.getHeight()) / 2;
        float by = (getHeight() + sBitmap.getHeight()) / 2;

        if (cx > lX && cx < rX && cy > ty && cy < by) {
            if (animControl.isRunning()) {
                return;
            }
            isLove = !isLove;
            if (isLove) {
                animControl();
            } else {
                postInvalidate();
            }
        }
    }



    private void animControl() {
        circleAnimSet.setStartDelay(300);
        love2BigAnim.setStartDelay(200);
        bigCircleAnim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                dotAnimSet.start();
            }
        });
        animControl.play(bitmapAnimSet).with(circleAnimSet);
        animControl.start();
    }


}
